home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / utility / uwserver.zip / uwserver.tar / lib / uw_options.c < prev    next >
C/C++ Source or Header  |  1991-01-25  |  7KB  |  259 lines

  1. /*
  2.  *    uw library - uw_options
  3.  *
  4.  * Copyright 1986 by John D. Bruner.  All rights reserved.  Permission to
  5.  * copy this program is given provided that the copy is not sold and that
  6.  * this copyright notice is included.
  7.  */
  8. #include <sys/types.h>
  9. #include <sys/file.h>
  10. #include <sys/time.h>
  11. #include <netinet/in.h>
  12. #include <strings.h>
  13. #include <signal.h>
  14. #include <errno.h>
  15.  
  16. #include "uwlib.h"
  17.  
  18. #ifndef FD_SET
  19. #define    FD_SET(n,p)    ((p)->fds_bits[0] |= (1 << (n)))
  20. #define    FD_CLR(n,p)    ((p)->fds_bits[0] &= ~(1 << (n)))
  21. #define    FD_ISSET(n,p)    ((p)->fds_bits[0] & (1 << (n)))
  22. #define    FD_ZERO(p)    ((p)->fds_bits[0] = 0)
  23. #define    FD_SETSIZE    (NBBY*sizeof(long))
  24. #endif
  25.  
  26. #ifndef sigmask
  27. #define sigmask(m)    (1 << ((m)-1))
  28. #endif
  29.  
  30. #ifndef htons
  31. /* These should have been defined in <netinet/in.h>, but weren't (in 4.2BSD) */
  32. extern unsigned short htons(), ntohs();
  33. extern unsigned long htonl(), ntohl();
  34. #endif
  35.  
  36. static UWIN *fdmap;
  37. static int (*oldsigio)();
  38. static struct fd_set fdmask;
  39. static int nfds;
  40.  
  41. extern char *malloc();
  42.  
  43. uw_optinit(fd, uwin)
  44. int fd;
  45. UWIN uwin;
  46. {
  47.     register int i, flags;
  48.     static int first = 1;
  49.     extern uw_optinput();
  50.  
  51.     /*
  52.      * The first time through, allocate the file descriptor map and
  53.      * bitmask, and cause SIGIO traps to be handled by uw_optinput.
  54.      */
  55.     if (first) {
  56.         first = 0;
  57.         nfds = getdtablesize();
  58.         fdmap = (UWIN *)malloc((unsigned)(sizeof(UWIN)*nfds));
  59.         if (fdmap != (UWIN *)0)
  60.             for (i = 0; i < nfds; i++)
  61.                 fdmap[i] = (UWIN)0;
  62.         oldsigio = signal(SIGIO, uw_optinput);
  63.         FD_ZERO(&fdmask);
  64.     }
  65.  
  66.     /*
  67.      * Add the new control fd to the map and mask.  Set the owner
  68.      * to this process
  69.      */
  70.     if (fd >= 0 && fd < nfds && uwin != (UWIN)0 && fdmap != (UWIN *)0) {
  71.         fdmap[fd] = uwin;
  72.         FD_SET(fd, &fdmask);
  73. #ifdef SETOWN_BUG
  74.         (void)fcntl(fd, F_SETOWN, -getpid());
  75. #else
  76.         (void)fcntl(fd, F_SETOWN, getpid());
  77. #endif
  78.         if ((flags = fcntl(fd, F_GETFL, 0)) >= 0)
  79.             (void)fcntl(fd, F_SETFL, flags|FASYNC|FNDELAY);
  80.         uwin->uwi_ipclen = 0;
  81.     }
  82. }
  83.  
  84. uw_optdone(fd)
  85. {
  86.     register int flags;
  87.  
  88.     /*
  89.      * Turn off asynchronous I/O notification and remove the
  90.      * map and mask information for "fd".  We do not close the
  91.      * file descriptor, however -- the caller is expected to
  92.      * take care of that.
  93.      */
  94.     if (fd >= 0 && fd < nfds && fdmap != (UWIN *)0) {
  95.         if ((flags = fcntl(fd, F_GETFL, 0)) >= 0)
  96.             (void)fcntl(fd, F_SETFL, flags&~FASYNC);
  97.         else
  98.             (void)fcntl(fd, F_SETFL, 0);
  99.         (void)fcntl(fd, F_SETFL, 0);
  100.         fdmap[fd] = (UWIN)0;
  101.         FD_CLR(fd, &fdmask);
  102.     }
  103. }
  104.  
  105. static
  106. uw_optinput(sig, code, scp)
  107. int sig, code;
  108. struct sigcontext *scp;
  109. {
  110.     register int k, n, fd;
  111.     register UWIN uwin;
  112.     register struct uwoption *uwop;
  113.     register union uwoptval *uwov;
  114.     uwopt_t optnum;
  115.     uwoptcmd_t optcmd;
  116.     uwfnptr_t userfn;
  117.     int oldmask;
  118.     struct timeval timeo;
  119.     struct fd_set ready;
  120.     extern int errno;
  121.  
  122.     /*
  123.      * This routine is called when input is waiting on a control
  124.      * file descriptor.
  125.      */
  126.     oldmask = sigblock(sigmask(SIGALRM));
  127.     do {
  128.         ready = fdmask;
  129.         timeo.tv_sec = 0;
  130.         timeo.tv_usec = 0;
  131.         n = select(nfds, &ready, (struct fd_set *)0,
  132.                (struct fd_set *)0, &timeo);
  133.         if (n < 0 && errno == EBADF) {
  134.             /*
  135.              * One of the file descriptors that we asked for
  136.              * is no longer valid.  This isn't supposed to
  137.              * happen; however, we try to handle it by testing
  138.              * each bit individually and eliminating the bad
  139.              * ones.
  140.              */
  141.             for (fd=0; fd < nfds; fd++) {
  142.                 if (FD_ISSET(fd, &fdmask)) {
  143.                     do {
  144.                         ready = fdmask;
  145.                         timeo.tv_sec = 0;
  146.                         timeo.tv_usec = 0;
  147.                         k = select(nfds, &ready,
  148.                             (struct fd_set *)0,
  149.                             (struct fd_set *)0, &timeo);
  150.                         if (k < 0 && errno == EBADF) {
  151.                             fdmap[fd] = (UWIN)0;
  152.                             FD_CLR(fd, &fdmask);
  153.                         }
  154.                     } while (n < 0 && errno == EINTR);
  155.                 }
  156.             }
  157.         }
  158.     } while (n < 0 && errno == EINTR);
  159.  
  160.     for (fd=0; n > 0 && fd < nfds; fd++) {
  161.         if (FD_ISSET(fd, &ready)) {
  162.             n--;
  163.             uwin = fdmap[fd];
  164.             while ((k = getmesg(fd, uwin)) > 0) {
  165.                 uwin->uwi_ipclen = 0;    /* for next time */
  166.                 if (uwin->uwi_ipcbuf.uwip_cmd == UWC_OPTION) {
  167.                     uwop = &uwin->uwi_ipcbuf.uwip_option;
  168.                     uwov = &uwop->uwop_val;
  169.                     optnum = ntohs(uwop->uwop_opt);
  170.                     optcmd = ntohs(uwop->uwop_cmd);
  171.                     if (optcmd == UWOC_SET)
  172.                         uw_ntoh(uwin->uwi_type, optnum,
  173.                             (char *)uwov);
  174.                     if (optcmd == UWOC_SET) switch(optnum) {
  175.                     case UWOP_VIS:
  176.                         uwin->uwi_vis = !!uwov->uwov_6bit;
  177.                         break;
  178.                     case UWOP_TYPE:
  179.                         if (uwov->uwov_6bit<UW_NWTYPES)
  180.                             uwin->uwi_type=uwov->uwov_6bit;
  181.                         break;
  182.                     case UWOP_POS:
  183.                         uwin->uwi_pos.uwp_v = uwov->uwov_point.v;
  184.                         uwin->uwi_pos.uwp_h = uwov->uwov_point.h;
  185.                         break;
  186.                     case UWOP_TITLE:
  187.                         (void)strncpy(uwin->uwi_title,
  188.                             uwov->uwov_string,
  189.                             sizeof uwin->uwi_title);
  190.                         break;
  191.                     case UWOP_WSIZE:
  192.                         uwin->uwi_wsize.uwp_v = uwov->uwov_point.v;
  193.                         uwin->uwi_wsize.uwp_h = uwov->uwov_point.h;
  194.                         break;
  195.                     }
  196.                     if (optnum == UWOP_TYPE &&
  197.                         optcmd == UWOC_SET &&
  198.                         uwov->uwov_6bit < UW_NWTYPES)
  199.                         uwin->uwi_type=uwov->uwov_6bit;
  200.                     userfn = uwin->uwi_options[optnum].uwi_optfn;
  201.                     if (userfn != (uwfnptr_t)0)
  202.                         (*userfn)(uwin, optnum,
  203.                               optcmd, uwov);
  204.                 }
  205.             }
  206.             if (k < 0)
  207.                 (void)uw_detach(uwin);    /* I/O error or EOF */
  208.         }
  209.     }
  210.     (void)sigsetmask(oldmask);
  211.  
  212.     /*
  213.      * Finally, if "oldsigio" is not SIG_DFL, call it.
  214.      */
  215.     if (oldsigio != SIG_DFL)
  216.         (*oldsigio)(sig, code, scp);
  217. }
  218.  
  219. static
  220. getmesg(fd, uwin)
  221. register int fd;
  222. register UWIN uwin;
  223. {
  224.     register int len;
  225.     register char *cp;
  226.  
  227.     /*
  228.      * Read some more bytes from control socket "fd" into the input
  229.      * buffer.  Return 1 if the message is now complete, -1 if an
  230.      * EOF was reached, or 0 otherwise.  Before returning 1, the byte
  231.      * order of the common parameters (command, length) is changed
  232.      * from network to host order.
  233.      */
  234.     cp = (char *)&uwin->uwi_ipcbuf + uwin->uwi_ipclen;
  235.     if (uwin->uwi_ipclen < sizeof(uwin->uwi_ipcbuf.uwip_len)) {
  236.         len = read(fd, cp, sizeof uwin->uwi_ipcbuf.uwip_len - uwin->uwi_ipclen);
  237.         if (len == 0 || (len < 0 && errno != EWOULDBLOCK))
  238.             return(-1);
  239.         if (len < 0)
  240.             return(0);
  241.         if ((uwin->uwi_ipclen +=len) < sizeof uwin->uwi_ipcbuf.uwip_len)
  242.             return(0);
  243.         uwin->uwi_ipcbuf.uwip_len = ntohs(uwin->uwi_ipcbuf.uwip_len);
  244.         if (uwin->uwi_ipcbuf.uwip_len==sizeof uwin->uwi_ipcbuf.uwip_len)
  245.             return(1);
  246.         cp += len;
  247.     }
  248.     if (uwin->uwi_ipcbuf.uwip_len > sizeof(struct uwipc))
  249.         uwin->uwi_ipcbuf.uwip_len = sizeof(struct uwipc);
  250.     len = read(fd, cp, uwin->uwi_ipcbuf.uwip_len - uwin->uwi_ipclen);
  251.     if (len == 0 || (len < 0 && errno != EWOULDBLOCK))
  252.         return(-1);
  253.     if ((uwin->uwi_ipclen += len) == uwin->uwi_ipcbuf.uwip_len) {
  254.         uwin->uwi_ipcbuf.uwip_cmd = ntohs(uwin->uwi_ipcbuf.uwip_cmd);
  255.         return(1);
  256.     } else
  257.         return(0);
  258. }
  259.